package org.jeecg.modules.travel.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.travel.code.CheckStatusCode;
import org.jeecg.modules.travel.dto.attraction.AppAttractionPageDto;
import org.jeecg.modules.travel.dto.attraction.AttractionAddDto;
import org.jeecg.modules.travel.dto.attraction.AttractionAuthDto;
import org.jeecg.modules.travel.dto.attraction.AttractionEditDto;
import org.jeecg.modules.travel.entity.*;
import org.jeecg.modules.travel.mapper.*;
import org.jeecg.modules.travel.service.IJhAttractionService;
import org.jeecg.modules.travel.util.AMapUtils;
import org.jeecg.modules.travel.vo.CompositeKey;
import org.jeecg.modules.travel.vo.attraction.AppAttractionDetailVo;
import org.jeecg.modules.travel.vo.attraction.AppAttractionRecordVo;
import org.jeecg.modules.travel.vo.attraction.AttractionListVo;
import org.jeecg.modules.travel.vo.attraction.PcAttractionDetailVo;
import org.jeecg.modules.travel.vo.attractionFile.AttractionFileVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 景点表
 * @Author: jeecg-boot
 * @Date:   2025-04-19
 * @Version: V1.0
 */
@Service
public class JhAttractionServiceImpl extends ServiceImpl<JhAttractionMapper, JhAttraction> implements IJhAttractionService {

    private static final int RANDOM_TOTAL = 100; // 随机总量
    private static final long EXPIRE_TIME = 3600L; // Redis 过期时间秒
    @Autowired
    private RedisUtil redisUtil;
    @Resource
    private JhAttractionFileMapper jhAttractionFileMapper;
    @Resource
    private JhThemeMapper jhThemeMapper;
    @Resource
    private JhLikesMapper jhLikesMapper;
    @Resource
    private JhFavoritesMapper jhFavoritesMapper;

    @Override
    public IPage<AppAttractionRecordVo> queryAttractionList(AppAttractionPageDto dto, String userId, Page<JhAttraction> page, QueryWrapper<JhAttraction> queryWrapper) {
        if (StringUtils.isNotBlank(dto.getKeyword())) {
            List<JhTheme> list = jhThemeMapper.selectList(new QueryWrapper<JhTheme>().lambda().like(JhTheme::getThemeName, dto.getKeyword()));
            List<String> ids = list.stream().map(JhTheme::getId).collect(Collectors.toList());
            queryWrapper.lambda().and(eq -> eq.like(JhAttraction::getAttractionName,dto.getKeyword())
                    .or().like(JhAttraction::getAttractionDescription, dto.getKeyword())
                    .or().in(!ids.isEmpty(), JhAttraction::getAttractionTheme,ids));
        }
        String pointType = StringUtils.isNotBlank(dto.getPointType()) ? dto.getPointType() : "0";
        if (pointType.equals("0")) {
            queryWrapper.lambda().orderByDesc(JhAttraction::getLikeCount);
        } else if (pointType.equals("1")) {
            if (dto.getLon() != null && dto.getLat() != null) {
                queryWrapper.orderByAsc("distance");
            }
        } else if (pointType.equals("2")) {
            if (dto.getLon() != null && dto.getLat() != null) {
                queryWrapper.orderByDesc("distance");
            }
        }
        IPage<AppAttractionRecordVo> pageList = baseMapper.queryAttractionList(page,queryWrapper,dto.getLon(), dto.getLat());
        if (pageList.getRecords() != null && !pageList.getRecords().isEmpty()) {
            List<String> ids = pageList.getRecords().stream().map(AppAttractionRecordVo::getId).collect(Collectors.toList());
            //1、图片、音频、视频
            List<JhAttractionFile> list = jhAttractionFileMapper.selectList(new QueryWrapper<JhAttractionFile>()
                    .lambda().in(JhAttractionFile::getAttractionId,ids));
            Map<CompositeKey, List<AttractionFileVo>> map = list.stream().collect(Collectors
                    .groupingBy(item -> new CompositeKey(item.getAttractionId(),item.getType()), Collectors.mapping(
                            i -> AttractionFileVo.builder().type(i.getType()).path(i.getPath()).build(),
                            Collectors.toList()
                    )));
            Map<String, JhLikes> likesMap = new HashMap<>();
            Map<String, JhFavorites> favoritesMap = new HashMap<>();
            if (StringUtils.isNotBlank(userId)) {
                //2、点赞
                List<JhLikes> likes = jhLikesMapper.selectList(new QueryWrapper<JhLikes>().lambda()
                        .eq(JhLikes::getUserId,userId)
                        .eq(JhLikes::getContentType, "0")
                        .in(JhLikes::getContentId, ids));
                likesMap = likes.stream().collect(Collectors.toMap(JhLikes::getContentId, i -> i));
                //3、收藏
                List<JhFavorites> favorites = jhFavoritesMapper.selectList(new QueryWrapper<JhFavorites>().lambda()
                        .eq(JhFavorites::getUserId,userId)
                        .eq(JhFavorites::getContentType, "0")
                        .in(JhFavorites::getContentId, ids));
                favoritesMap = favorites.stream().collect(Collectors.toMap(JhFavorites::getContentId, i -> i));
            }
            for (AppAttractionRecordVo record : pageList.getRecords()) {
                if (dto.getLon() != null && dto.getLat() != null) {
                    int distance = AMapUtils.getDistance(dto.getLon(), dto.getLat(), record.getLongitude(), record.getLatitude());
                    record.setDistance(BigDecimal.valueOf(distance).divide(new BigDecimal(1000),2, RoundingMode.HALF_UP));
                }
                if (StringUtils.isNotBlank(userId)) {
                    record.setIsLike(likesMap.get(record.getId()) != null ? "1" : "0");
                    record.setIsFavorite(favoritesMap.get(record.getId()) != null ? "1" : "0");
                }
                List<AttractionFileVo> imgFile = map.get(new CompositeKey(record.getId(), 0));
                List<AttractionFileVo> MpFile = map.get(new CompositeKey(record.getId(), 1));
                List<AttractionFileVo> videoFile = map.get(new CompositeKey(record.getId(), 2));
                record.setImgFile(imgFile == null ? new ArrayList<>() : imgFile);
                record.setMpFile(MpFile == null ? new ArrayList<>() : MpFile);
                record.setVideoFile(videoFile == null ? new ArrayList<>() : videoFile);
            }
        }
        return pageList;
    }

    @Override
    public AppAttractionDetailVo appAttractionDetail(String id, String userId) {
        JhAttraction attraction = getById(id);
        if (attraction == null) {
            return null;
        }
        AppAttractionDetailVo detailVo = new AppAttractionDetailVo();
        BeanUtils.copyProperties(attraction,detailVo);
        //1、图片、音频、视频
        List<JhAttractionFile> list = jhAttractionFileMapper.selectList(new QueryWrapper<JhAttractionFile>()
                .lambda().eq(JhAttractionFile::getAttractionId,id));
        Map<CompositeKey, List<AttractionFileVo>> map = list.stream().collect(Collectors
                .groupingBy(item -> new CompositeKey(item.getAttractionId(),item.getType()), Collectors.mapping(
                        i -> AttractionFileVo.builder().type(i.getType()).path(i.getPath()).build(),
                        Collectors.toList()
                )));
        if (StringUtils.isNotBlank(userId)) {
            //2、点赞
            JhLikes likes = jhLikesMapper.selectOne(new QueryWrapper<JhLikes>().lambda()
                    .eq(JhLikes::getUserId, userId)
                    .eq(JhLikes::getContentType, "0")
                    .eq(JhLikes::getContentId, attraction.getId()));
            //3、收藏
            JhFavorites favorites = jhFavoritesMapper.selectOne(new QueryWrapper<JhFavorites>().lambda()
                    .eq(JhFavorites::getUserId, userId)
                    .eq(JhFavorites::getContentType, "0")
                    .in(JhFavorites::getContentId, attraction.getId()));
            detailVo.setIsLike(likes != null ? "1" : "0");
            detailVo.setIsFavorite(favorites != null ? "1" : "0");
        }
        List<AttractionFileVo> imgFile = map.get(new CompositeKey(id, 0));
        List<AttractionFileVo> MpFile = map.get(new CompositeKey(id, 1));
        List<AttractionFileVo> videoFile = map.get(new CompositeKey(id, 2));
        detailVo.setImgFile(imgFile == null ? new ArrayList<>() : imgFile);
        detailVo.setMpFile(MpFile == null ? new ArrayList<>() : MpFile);
        detailVo.setVideoFile(videoFile == null ? new ArrayList<>() : videoFile);
        return detailVo;
    }

    @Override
    @Transactional
    public String attractionAdd(AttractionAddDto dto) {
        JhAttraction attraction = new JhAttraction();
        BeanUtils.copyProperties(dto,attraction);
        baseMapper.insert(attraction);
        List<JhAttractionFile> fileList = new ArrayList<>();
        if (dto.getImgFile() != null && !dto.getImgFile().isEmpty()) {
            for (String s : dto.getImgFile()) {
                JhAttractionFile file = new JhAttractionFile();
                file.setAttractionId(attraction.getId());
                file.setType(0);
                file.setPath(s);
                fileList.add(file);
            }
        }
        if (dto.getMpFile() != null && !dto.getMpFile().isEmpty()) {
            for (String s : dto.getMpFile()) {
                JhAttractionFile file = new JhAttractionFile();
                file.setAttractionId(attraction.getId());
                file.setType(1);
                file.setPath(s);
                fileList.add(file);
            }
        }
        if (dto.getVideoFile() != null && !dto.getVideoFile().isEmpty()) {
            for (String s : dto.getVideoFile()) {
                JhAttractionFile file = new JhAttractionFile();
                file.setAttractionId(attraction.getId());
                file.setType(2);
                file.setPath(s);
                fileList.add(file);
            }
        }
        if (!fileList.isEmpty()) {
            for (JhAttractionFile file : fileList) {
                jhAttractionFileMapper.insert(file);
            }
        }
        return null;
    }

    @Override
    @Transactional
    public String attractionEdit(AttractionEditDto dto, String username) {
        JhAttraction attraction = getById(dto.getId());
        if (attraction == null) {
            return "景点不存在";
        }
        BeanUtils.copyProperties(dto,attraction);
        attraction.setUpdateBy(username);
        attraction.setUpdateTime(new Date());
        baseMapper.updateAttraction(attraction);
        jhAttractionFileMapper.delete(new QueryWrapper<JhAttractionFile>().lambda()
                .eq(JhAttractionFile::getAttractionId,dto.getId()));
        List<JhAttractionFile> fileList = new ArrayList<>();
        if (dto.getImgFile() != null && !dto.getImgFile().isEmpty()) {
            for (String s : dto.getImgFile()) {
                JhAttractionFile file = new JhAttractionFile();
                file.setAttractionId(attraction.getId());
                file.setType(0);
                file.setPath(s);
                fileList.add(file);
            }
        }
        if (dto.getMpFile() != null && !dto.getMpFile().isEmpty()) {
            for (String s : dto.getMpFile()) {
                JhAttractionFile file = new JhAttractionFile();
                file.setAttractionId(attraction.getId());
                file.setType(1);
                file.setPath(s);
                fileList.add(file);
            }
        }
        if (dto.getVideoFile() != null && !dto.getVideoFile().isEmpty()) {
            for (String s : dto.getVideoFile()) {
                JhAttractionFile file = new JhAttractionFile();
                file.setAttractionId(attraction.getId());
                file.setType(2);
                file.setPath(s);
                fileList.add(file);
            }
        }
        if (!fileList.isEmpty()) {
            for (JhAttractionFile file : fileList) {
                jhAttractionFileMapper.insert(file);
            }
        }
        return null;
    }

    @Override
    public IPage<AppAttractionRecordVo> randomAttractionList(AppAttractionPageDto dto, String userId) {
        List<String> allIds = baseMapper.selectRandomIds(RANDOM_TOTAL);
        String sessionKey = "recommend_" + UUID.randomUUID();
        redisUtil.set(sessionKey, JSON.toJSONString(allIds), EXPIRE_TIME);
        int fromIndex = (dto.getPageNo() - 1) * dto.getPageSize();
        int toIndex = Math.min(fromIndex + dto.getPageSize(), allIds.size());
        List<String> pageIds = fromIndex < allIds.size() ? allIds.subList(fromIndex, toIndex) : Collections.emptyList();
        List<AppAttractionRecordVo> voList = pageIds.isEmpty() ? Collections.emptyList() : baseMapper.randomAttractionList(pageIds);
        if (voList != null && !voList.isEmpty()) {
            List<String> ids = voList.stream().map(AppAttractionRecordVo::getId).collect(Collectors.toList());
            //1、图片、音频、视频
            List<JhAttractionFile> list = jhAttractionFileMapper.selectList(new QueryWrapper<JhAttractionFile>()
                    .lambda().in(JhAttractionFile::getAttractionId,ids));
            Map<CompositeKey, List<AttractionFileVo>> map = list.stream().collect(Collectors
                    .groupingBy(item -> new CompositeKey(item.getAttractionId(),item.getType()), Collectors.mapping(
                            i -> AttractionFileVo.builder().type(i.getType()).path(i.getPath()).build(),
                            Collectors.toList()
                    )));
            Map<String, JhLikes> likesMap = new HashMap<>();
            Map<String, JhFavorites> favoritesMap = new HashMap<>();
            if (StringUtils.isNotBlank(userId)) {
                //2、点赞
                List<JhLikes> likes = jhLikesMapper.selectList(new QueryWrapper<JhLikes>().lambda()
                        .eq(JhLikes::getUserId,userId)
                        .eq(JhLikes::getContentType, "0")
                        .in(JhLikes::getContentId, ids));
                likesMap = likes.stream().collect(Collectors.toMap(JhLikes::getContentId, i -> i));
                //3、收藏
                List<JhFavorites> favorites = jhFavoritesMapper.selectList(new QueryWrapper<JhFavorites>().lambda()
                        .eq(JhFavorites::getUserId,userId)
                        .eq(JhFavorites::getContentType, "0")
                        .in(JhFavorites::getContentId, ids));
                favoritesMap = favorites.stream().collect(Collectors.toMap(JhFavorites::getContentId, i -> i));
            }
            for (AppAttractionRecordVo record : voList) {
                if (dto.getLon() != null && dto.getLat() != null) {
                    int distance = AMapUtils.getDistance(dto.getLon(), dto.getLat(), record.getLongitude(), record.getLatitude());
                    record.setDistance(BigDecimal.valueOf(distance).divide(new BigDecimal(1000),2, RoundingMode.HALF_UP));
                }
                if (StringUtils.isNotBlank(userId)) {
                    record.setIsLike(likesMap.get(record.getId()) != null ? "1" : "0");
                    record.setIsFavorite(favoritesMap.get(record.getId()) != null ? "1" : "0");
                }
                List<AttractionFileVo> imgFile = map.get(new CompositeKey(record.getId(), 0));
                List<AttractionFileVo> MpFile = map.get(new CompositeKey(record.getId(), 1));
                List<AttractionFileVo> videoFile = map.get(new CompositeKey(record.getId(), 2));
                record.setImgFile(imgFile == null ? new ArrayList<>() : imgFile);
                record.setMpFile(MpFile == null ? new ArrayList<>() : MpFile);
                record.setVideoFile(videoFile == null ? new ArrayList<>() : videoFile);
            }
        }
        IPage<AppAttractionRecordVo> pageList = new Page<>();
        pageList.setRecords(voList);
        pageList.setPages(dto.getPageNo());
        pageList.setSize(dto.getPageSize());
        pageList.setTotal(allIds.size());
        return pageList;
    }

    @Override
    public IPage<AttractionListVo> queryPage(Page<JhAttraction> page, QueryWrapper<JhAttraction> queryWrapper) {
        List<AttractionListVo> returnList = new ArrayList<>();
        IPage<AttractionListVo> returnPage = new Page<>();
        //先查询默认的
        Page<JhAttraction> getDefaultPage = this.page(page, queryWrapper);
        List<JhAttraction> records = getDefaultPage.getRecords();
        //把所有的分类id 查出然后赋值返回
        if (records != null && !records.isEmpty()) {
            records.forEach(item -> {
                AttractionListVo attractionListVo = new AttractionListVo();
                BeanUtils.copyProperties(item, attractionListVo);
                returnList.add(attractionListVo);
            });
            returnPage.setRecords(returnList);
            returnPage.setTotal(getDefaultPage.getTotal());
            returnPage.setPages(getDefaultPage.getPages());
            returnPage.setSize(getDefaultPage.getSize());
        }
        return returnPage;
    }

    @Override
    public PcAttractionDetailVo pcAttractionDetail(String id) {
        JhAttraction attraction = getById(id);
        if (attraction == null) {
            return null;
        }
        PcAttractionDetailVo detailVo = new PcAttractionDetailVo();
        BeanUtils.copyProperties(attraction,detailVo);
        //1、图片、音频、视频
        List<JhAttractionFile> list = jhAttractionFileMapper.selectList(new QueryWrapper<JhAttractionFile>()
                .lambda().eq(JhAttractionFile::getAttractionId,id));
        Map<CompositeKey, List<AttractionFileVo>> map = list.stream().collect(Collectors
                .groupingBy(item -> new CompositeKey(item.getAttractionId(),item.getType()), Collectors.mapping(
                        i -> AttractionFileVo.builder().type(i.getType()).path(i.getPath()).build(),
                        Collectors.toList()
                )));
        List<AttractionFileVo> imgFile = map.get(new CompositeKey(id, 0));
        List<AttractionFileVo> MpFile = map.get(new CompositeKey(id, 1));
        List<AttractionFileVo> videoFile = map.get(new CompositeKey(id, 2));
        detailVo.setImgFile(imgFile == null ? new ArrayList<>() : imgFile);
        detailVo.setMpFile(MpFile == null ? new ArrayList<>() : MpFile);
        detailVo.setVideoFile(videoFile == null ? new ArrayList<>() : videoFile);
        return detailVo;
    }

    @Override
    public String attractionAuth(AttractionAuthDto dto, String userId) {
        JhAttraction attraction = getById(dto.getId());
        if (attraction == null) {
            return "景点不存在";
        }
        UpdateWrapper<JhAttraction> wrapper = new UpdateWrapper<>();
        wrapper.lambda().set(JhAttraction::getCheckStatus, dto.getCheckStatus())
                .set(JhAttraction::getCheckPeople, userId)
                .set(JhAttraction::getCheckTime, new Date())
                .set(JhAttraction::getCheckRemark, Objects.equals(dto.getCheckStatus(), CheckStatusCode.NOT_APPROVED)
                        ? dto.getCheckRemark() : null)
                .eq(JhAttraction::getId, dto.getId());
        boolean flag = update(wrapper);
        if (!flag) {
            return "审核失败";
        }
        return null;
    }

}
